#pragma once

using namespace std;

#include "api/GameInfo.h"
#include "Utils.h"


class PathFinder
{
public:
    PathFinder(const LevelInfo* level);
    ~PathFinder() { delete m_Data; }
    bool FindPath(const Vector2& start, const Vector2& dest, Path& res, bool smooth = true, bool include_start = false);
    void SmoothPath(const Path& path, Path& res_path);

private:
    enum { BLOCKED = 0, WALKABLE };
    enum { NOT_SET = 0, CLOSED, OPEN };

    struct Node
    {
        uint index;
        float g_score;
        float f_score;
        uint flag; // open|closed 
        uint come_from;

        Node() : index(0), g_score(-1.f), f_score(-1.f), flag(NOT_SET), come_from(0xFFFFFFFF) {}
        Node(uint i, float g, float f) : index(i), g_score(g), f_score(f), flag(NOT_SET), come_from(0xFFFFFFFF) {}
        //Node(const Node& n) : index(n.index), g_score(n.g_score), f_score(n.f_score) {}

        bool operator== (const Node& n) { return n.index == index; }
    };

    void InitData();
    float HeuristicCostEstimate(const Vector2& start, const Vector2& end);
    uint GetIndex(const Vector2& v) { return (uint) v.x + (uint) v.y * m_Width; }
    Vector2 GetPosition(uint index) { return Vector2((float) (index % m_Width), (float) (index / m_Width)); }
    Node& FindNodeWithLowestScore(vector<uint>& set);

    void GetNeighbors4(uint index, vector<uint>& neighbors);
    void GetNeighbors8(uint index, vector<uint>& neighbors);
    void ReconstructPath(Path& path, uint start_index, uint end_index, bool smooth);
    
    uint m_Width;
    uint m_Height;
    uchar* m_Data;
    Node* m_Nodes;
    const LevelInfo* m_Level;
};
